home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Book Chapters
/
02 - Basic Game Graphics
/
HSV Demo 2 ƒ
/
HSV Demo2.c
< prev
Wrap
C/C++ Source or Header
|
1995-03-30
|
9KB
|
311 lines
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//
// HSV Demo 2.c
//
// Demonstrates drawing with HSV colors and building a CLUT
// from scratch. Nicer colors than HSV Demo 1 because we're
// customizing our color environment with our spiffy clut.
// HSV Demo 1 used a nice but insufficient CLUT provided by
// the System.
//
// Also shows how to use the Process Manager to obtain the
// name of the application.
//
// History:
//
// 950225 jb: Written
// 950305 jb: Cleaned up and commented
//
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
// __#Defines________________________________________________________________________
#define kMainWindowResID 1000
#define kAppColorTableResID 72 //ID of nice, 256-color palette provided by System
#define kSleepTicks 0xFFFFFFFF //relinquish all time; don't want null events
// __#Headers________________________________________________________________________
#include <Palettes.h>
#include <math.h>
#include "Utils.h" //for EnviroCheck
// __#Protos_________________________________________________________________________
// __ Macros_________________________________________________________________________
// __ Enums__________________________________________________________________________
// __ Typedefs_______________________________________________________________________
// __ Static Protos__________________________________________________________________
static void ToolBoxInit(void);
static Boolean OpenMainWindow( void );
static void ShowHSVCircle2( void );
static void WaitForQuit( void );
static void GetAppName(char *pascalName);
// __ Extern Globals_________________________________________________________________
// __ Static Globals_________________________________________________________________
static OSErr gErr;
static WindowPtr gMainWindow;
static Str32 gAppName;
// __ Functions______________________________________________________________________
//____ main __________________________________________________________________________
//
void main( void )
{
ToolBoxInit();
if (!EnviroCheck())
ExitToShell();
GetAppName((char *)gAppName);
if (!OpenMainWindow())
ExitToShell();
ShowHSVCircle2();
WaitForQuit();
if(NULL != gMainWindow)
DisposeWindow(gMainWindow);
}//main
//____ ToolBoxInit __________________________________________________________________________
//
// Basic initialization.
//
static void ToolBoxInit( void )
{
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(NULL);
InitCursor();
FlushEvents(everyEvent, 0);
} //ToolBoxInit
//____ OpenMainWindow __________________________________________________________________________
//
// Create CLUT from scratch, filling it with customized colors suitable for our
// nefarious HSV circle-drawing needs. Open a window
//
// Open our window, install palette built from a resource CTable.
// provided by the System.
//
// All entries in palette marked pmTolerant, with a tolerance of 0x5000.
//
static Boolean OpenMainWindow( void )
{
PaletteHandle appPalette; // the palette that we will make the window's palette
CTabHandle tempColorTable;
HSVColor ourHSV;
RGBColor resultingRGB;
ColorSpecPtr aClrSpec;
short x;
ourHSV.hue = 0;
ourHSV.saturation = 65535;
ourHSV.value = 65535;
//create a CLUT in memory
tempColorTable = (CTabHandle)NewHandle(sizeof(ColorTable) + (256 * sizeof(ColorSpec)));
(**tempColorTable).ctSeed = GetCTSeed();
(**tempColorTable).ctFlags = 0x0;
(**tempColorTable).ctSize = 255;
aClrSpec = (**tempColorTable).ctTable;
//make a neutral gray for the background
resultingRGB.red = resultingRGB.blue = resultingRGB.green = 32768;
aClrSpec->rgb = resultingRGB;
aClrSpec++;
//create a rainbow of colors and stuff them into consecutive rgbs in the CLUT.
for (x = 2; x < 255; x++)
{
ourHSV.hue += 65535 / 254;
HSV2RGB(&ourHSV,&resultingRGB);
aClrSpec->rgb = resultingRGB;
aClrSpec++;
}
// create and show the window, make sure it's frontmost
gMainWindow = GetNewCWindow( kMainWindowResID, ( Ptr )NULL, ( WindowPtr ) -1 );
if (NULL == gMainWindow) //real apps should handle this gracefully
return FALSE;
SetWTitle(gMainWindow,gAppName);
ShowWindow( gMainWindow );
SetPort( gMainWindow );
//create a new Palette for our window, passing in tempColorTable and all
//of its bright, shiny colors
appPalette = NewPalette( 256, tempColorTable, pmTolerant, 0x0000 );
//pop the new Palette into the window
NSetPalette( gMainWindow, appPalette, pmAllUpdates );
//tell the hardware that the color for our window's changed and
//to make sure the colors our Palette is requesting are available.
ActivatePalette(gMainWindow);
//release memory occupied by our temporary ColorTable.
DisposeCTable(tempColorTable);
return TRUE;
}//OpenWindowWithCTableID
//____ ShowHSVCircle2 __________________________________________________________________________
//
// This is similar to the HSV Demo 1 function:
//
// Walk incrementally around the perimeter of the HSV color wheel, creating HSV colors
// on each step, translating them to RGB, and then drawing a dot with that color
// on a circle corresponding the color's origin on the HSV wheel.
//
// Changing the value of kNumCircles to a number greater than one will cause more HSV
// circles to be drawn, each of which will exhibit increasing Saturation and Value.
//
// However, since we've craftily installed a Palette with the colors we know we'll need,
// the image rendered is much nicer.
//
// Also, note that the string drawn looks nifty as it cycles from color to color. It does,
// however, have to be drawn every time. Keep this in mind when we explore Palette Animation.
//
static void ShowHSVCircle2( void )
{
#define kNumSteps 256 //defines how many dots
#define mThetaStepSize (6.283 / kNumSteps) //how far around our circle to go
#define mColorStepSize (65535 / kNumSteps) //how far to go around color wheel per dot
#define kNumCircles 1 // <=== try changing this to values like 5 or 10
#define kRadius 120 //max radius of our circle
#define mRadiusStep (kRadius / kNumCircles) //how much to enlarge each circle
#define mSatValStep (65535 / kNumCircles) //amount to increments saturation and value
#define kHalfRectSize 20 //halve length to make centering easy
short step;
short x, y, cenX, cenY;
double theta;
Rect aRect;
short theRadius;
short circleNum;
HSVColor ourHSV;
RGBColor resultingRGB;
TextFont(0); //use Chicago
TextSize(12);
cenX = qd.thePort->portRect.right / 2;
cenY = qd.thePort->portRect.bottom / 2;
//use a neutral gray for the background
resultingRGB.red = resultingRGB.blue = resultingRGB.green = 32768;
RGBForeColor(&resultingRGB);
PaintRect(&qd.thePort->portRect);
//start out with full red
ourHSV.hue = 0;
ourHSV.saturation = 0;
ourHSV.value = 0;
theRadius = 0;
for (circleNum = 0; circleNum < kNumCircles; circleNum++)
{
theRadius += mRadiusStep;
ourHSV.saturation += mSatValStep;
ourHSV.value += mSatValStep;
//draw HSV circle
for (step = 0, theta = 0.0; step < kNumSteps; step++)
{
MoveTo(20,20);
DrawString(gAppName);
theta += mThetaStepSize;
x = cenX + theRadius * cos(theta);
y = cenY - theRadius * sin(theta);
ourHSV.hue += mColorStepSize; //move clockwise along color wheel
HSV2RGB(&ourHSV,&resultingRGB);
RGBForeColor(&resultingRGB);
SetRect(&aRect, x - kHalfRectSize, y - kHalfRectSize, x + kHalfRectSize, y + kHalfRectSize);
PaintOval(&aRect);
}
}//for circleNum
}//ShowHSVCircle2
//____ WaitForQuit __________________________________________________________________________
//
// Hangs out until there is any keyboard or mouse activity. A rather plain instance of
// an event loop; a real program would be more robust.
//
static void WaitForQuit( void )
{
Boolean wait;
EventRecord theEvent;
wait = TRUE;
while (wait)
{
if(WaitNextEvent(everyEvent, &theEvent, kSleepTicks, 0L))
{
switch (theEvent.what)
{
case mouseDown:
case keyDown:
wait = FALSE;
break;
}//switch (theEvent.what)
}//if WaitNextEvent
}//while
}//WaitForQuit
//____ GetAppName __________________________________________________________________________
//
// This happy function does just what it says. But, instead of using some scary (and
// soon-to-be obsolete) low memory global to get at the application's name, we use
// the Process Manager, even if it does force us through a couple of non-intuitive
// hoops in the, uh, process...
//
static void GetAppName(char *pascalName)
{
ProcessSerialNumber PSN;
ProcessInfoRec info;
gErr = GetCurrentProcess(&PSN);
if (noErr != gErr)
goto Xit;
//stick stuff into info rec before calling GetProcessInformation
info.processInfoLength = sizeof( ProcessInfoRec );
info.processAppSpec = nil;
info.processName = ( StringPtr ) pascalName;
gErr = GetProcessInformation(&PSN,&info);
if (noErr != gErr)
goto Xit;
Xit:
if (noErr != gErr) //was there an error?
{
BlockMove("\8Untitled", pascalName, 9);
}
return;
}//GetAppName